﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using ALDIOrganizer;
using ALDIOrganizer.Properties;

namespace Generator
{
    /// <summary>
    /// This static class contains methods and functionality which allows to detect situations where the solution does not exist
    /// </summary>
    public static class DetectImpossibilities
    {
        
        /// <summary>
        /// Tries to solve the problem separately for each Day.
        /// </summary>
        /// <remarks>
        /// This helps to avoid the expotential complexity of solving 7 bits at once.
        /// E.g. if there is 300 combinatorical possibilities of assigning people to Shifts for each Day,
        /// then in worst case the engine could be forced to analyze 300^7 = 218 700 000 000 000 000 possibilities
        /// before admitting defeat.
        /// If we analyze it Day by Day, we only have to examine 300*7 = 2100 scenarios.
        /// </remarks>
        /// <param Name="Template"></param>
        /// <returns>1s in the bool array represent the bits for which no solution was found. Last bit says whether there was any problem.</returns>
        
        public static bool[] DayByDayTest(Rota rota, Template template, BackgroundWorker worker)
        {
            /* e.g. 0001000 1 = there was an issue with Thursday! */
            var impossibleDays = new bool[8];
            var engines = new Engine[7];
            bool lastbit = false;

            worker.ReportProgress(0,
                new[]
                    {
                        String.Empty,
                        Resources.GENERATOR_SeekingImpossibilities
                    });

            for (int day = 0; day < 7; day++)
            {
                if (worker.CancellationPending) return null;                

                engines[day] = new Engine();
                var b = engines[day].ImportData(rota, template, new[] { (Weekday)day });
                if (b < 0)
                {
                    impossibleDays[day] = true;
                    lastbit = true;
                }
                else
                {
                    var g = engines[day].Go(
                        engines[day].solution,
                        -1,
                        -1,
                        true,
                        null);
                    if (g < 0)
                    {
                        impossibleDays[day] = true;
                        lastbit = true;
                    }
                    else
                    {
                        impossibleDays[day] = false;
                    }
                }
                worker.ReportProgress(
                    ((day + 1) * 100) / 7,
                    new[]
                    { 
                        Time.NameOfDay(day),
                        Resources.GENERATOR_SeekingImpossibilities
                    } );
            }
            impossibleDays[7] = lastbit;
            return impossibleDays;
        }
    }
}
